// hdu5739
// 题意：
// 给定一个n(<=10^5)个节点m(<=2*10^5)条边的无向图，每个节点都有一个权重w[i]，
// 现在对于每个节点i定义函数z[i]表示去掉这个点i之后，所有联通子图的权重的
// 和，一个联通子图的权重定义为所有节点的权值的乘积。
//
// 最后要求 ans=sigma(i * z[i])，答案模除 10^9 + 7。
//
// 题解：
// 这题和 bzoj1123 很类似，只需要考虑在 tarjan dfs树的过程中维护出答案就行，
// 在 dfs 树上一个节点u的儿子们，其中一些会与u的祖先相连，有些不会，
// 不会的相当于是u到这个儿子的边是一条割边，所以可以单独算出这个子树的权。
// 如果是和u祖先相连的，那么这个子树的权算到祖先里（可以通过整个联通
// 分量的权除以u儿子不和祖先相连权的积的结果来算，逆元一下就行）。
//
// 然后要注意原图不一定是联通的，然后使劲维护就可以了。
//
// ml:run = time -p $bin < input > output
#include <iostream>
#include <algorithm>
#include <vector>

using ll = long long;
ll const mo = 1000000007;
int const maxn = 100007;
int w[maxn];
int dfn[maxn], low[maxn], co[maxn];
ll z[maxn], prod[maxn], all[maxn];
int all_size[maxn], size[maxn];
int n, m, tick, co_tick;

std::vector<std::vector<int>> tree;

void add_edge(int u, int v)
{
    tree[u].push_back(v);
    tree[v].push_back(u);
}

void init()
{
    tick = co_tick = 0;
    tree.clear(); tree.resize(n + 1);
    std::fill(dfn, dfn + n + 1, 0);
    std::fill(z, z + n + 1, 0);
}

void extended_gcd(ll a, ll b, ll & d, ll & x, ll & y)
{
	if (!b) { d = a; x = 1; y = 0; }
	else {
		extended_gcd(b, a % b, d, y, x);
		y -= x * (a/b);
	}
}

ll inverse(ll t, ll p)
{
	ll x, y, d;
	extended_gcd(t, p, d, x, y);
	return (x % p + p) % p;
}

void mul(ll & u, ll v) { u *= v; u %= mo; }
void add(ll & u, ll v) { u += v; u %= mo; }

void get_all(int u, int f)
{
    dfn[u] = 1;
    all_size[co_tick]++;
    mul(all[co_tick], w[u]); co[u] = co_tick;
    for (auto v : tree[u])
        if (v != f && !dfn[v]) get_all(v, u);
}

void tarjan(int u, int f)
{
    low[u] = dfn[u] = ++tick;
    prod[u] = w[u];
    ll tmp = w[u];
    size[u] = 1;
    for (auto v : tree[u]) {
        if (v == f) continue;
        if (!dfn[v]) {
            tarjan(v, u);
            mul(prod[u], prod[v]);
            low[u] = std::min(low[u], low[v]);
            size[u] += size[v];

            if (dfn[u] <= low[v]) {
                add(z[u], prod[v]);
                mul(tmp, prod[v]);
            }
        } else
            low[u] = std::min(low[u], dfn[v]);
    }

    ll t = (all[co_tick] * inverse(tmp, mo)) % mo;
    if (size[u] != all_size[co_tick]) add(z[u], t);
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    int T; std::cin >> T;
    while (T--) {
        std::cin >> n >> m;
        init();
        for (int i = 1; i <= n; i++) std::cin >> w[i];
        for (int i = 0, x, y; i < m; i++) {
            std::cin >> x >> y;
            add_edge(x, y);
        }

        for (int i = 1; i <= n; i++)
            if (!dfn[i]) {
                all[++co_tick] = 1;
                all_size[co_tick] = 0;
                get_all(i, -1);
            }

        co_tick = 0;
        std::fill(dfn, dfn + n + 1, 0);
        for (int i = 1; i <= n; i++)
            if (!dfn[i]) {
                co_tick++;
                tarjan(i, -1);
            }

        ll sum = 0;
        for (int i = 1; i <= co_tick; i++)
            add(sum, all[i]);

        for (int i = 1; i <= n; i++)
            add(z[i], (sum - all[co[i]] + mo) % mo);

        ll ans = 0;
        for (int i = 1; i <= n; i++)
            add(ans, (i * z[i]) % mo);

        std::cout << ans << "\n";
    }
}

